#ifndef THREAD_H
#define THREAD_H

#include "circuitgraph.h"
#include "graphModel.h"
#include "extendedtimingparser.h"
#include "extendedlibparser.h"
#include "parser_helper.h"
#include <iostream>
#include <pthread.h>
#include "coneSampling.h"

#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/astar_search.hpp>
#include <boost/config.hpp>

using namespace std ;

struct _threadArgument
{
	int start ;
	int end ;
	bool coarse ;
	CircuitGraph* graphPtr ;
	Cone*		  conePtr ;
} ;

class Thread {
  private:
        // Prevent copying or assignment
        //Thread& operator=( const Thread& rhs ) ;
  protected:
        
        void *arg ;
        static void *exec(void *thr) ;
		
  public:
        
        pthread_t _id ;
        Thread() ;
        //Thread( const Thread& arg ) ;
        virtual ~Thread() ;
        void start(void *arg) ;
        void join() ;
        virtual void run() = 0 ;
        
} ;

Thread::Thread() {
	cout << "Thread::Thread()" << endl ;
}

Thread::~Thread() {
	cout << "Thread::~Thread()" << endl ;
}

void Thread::start(void *arg) {
	int ret ;
	this->arg = arg ;
	
	if ((ret = pthread_create(&_id, NULL, &Thread::exec, this)) != 0 ) {
		cout << ret << endl ;
		throw "Error" ;
	}
}

void Thread::join() {
	// Allow the thread to wait for the termination status
	pthread_join(_id, NULL) ;
}

// Function that is to be executed by the thread
void *Thread::exec(void *thr) {
	reinterpret_cast<Thread *> (thr)->run() ;
}

class MyThread : public Thread {
  public:
        void run () 
        {
                _threadArgument* inpArg = (_threadArgument*) arg ;
	
                int start = inpArg->start ;
                int end	  = inpArg->end ;
                bool coarse = inpArg->coarse ;
	
                cout << "Thread id: " << _id  << endl ;
                cout << "Start index: " << start << endl ;
                cout << "End index: " << end << endl ;
			
                for(int big_cone_id = start; big_cone_id < end; big_cone_id++)
                {
                        if(inpArg->conePtr->big_cones[big_cone_id].cone_ids.size() == 0 || 
                           (inpArg->conePtr->big_cones[big_cone_id].cone_ids.size() == 1 && 
                            inpArg->conePtr->cones[ inpArg->conePtr->big_cones[big_cone_id].cone_ids[0] ].critical_path.size() ==0))
                                continue;
            
                        //since we sort in the decreasing order before sampling is called
                        if(inpArg->conePtr->big_cones[big_cone_id].total_timing_viol == 0.0)
                                break;
            
                        cout<<"Optimizing Hybrid Cone "<< big_cone_id <<endl;
            
                        inpArg->conePtr->find_critical_gates_Hybcone( *(inpArg->graphPtr), big_cone_id, coarse);

                        int step_size = 2; int NSamples = inpArg->conePtr->ReducedCellSize;
            
                        if(inpArg->conePtr->big_cones[big_cone_id].done == 0)
                        {
                                //finish_first_round = 1;
                                inpArg->conePtr->sample_procedure( (*inpArg->graphPtr), big_cone_id, NSamples, coarse);
                        }
                        else
                        {
                                continue;
                                /*coarse = false;
                                  inpArg->conePtr->find_critical_gates_Hybcone((*inpArg->graphPtr), big_cone_id, coarse);
                                  while(inpArg->conePtr->sample_procedure((*inpArg->graphPtr), big_cone_id, NSamples, coarse) == false)
                                  {
                            
                                  NSamples += step_size;
                                  if(NSamples > 10)
                                  break;

                                  }*/
                        }
                }
        }
} ;
#include "coneSampling.hpp"
#endif
